
package ogame.utilities.defenses;

import java.util.ArrayList;
import java.util.HashMap;

/**
 *
 * @author scchang
 */
public class Defenses extends HashMap<DefenseType, Integer> {
    public String toString(){
        String output = "";
        for(DefenseType defense: this.keySet()){
            output += defense.name() + " : " + this.get(defense) + '\n';
        }
        if(output.equals("")){ output += '\n'; }
        return output;
    }
    
    public static Defenses parseDefenses(byte[] input){
        if(input.length == 0){
            throw new IllegalArgumentException("Unable to parse ships since "
                    + "input is length 0.");
        }
        Defenses defenses = new Defenses();
        
        int defenseNum = input[0];
        int currentIndex = 1;
        
        for(int i = 0; i < defenseNum; ++i){
            int defenseID = input[currentIndex];
            currentIndex++;
            int numContaining = input[currentIndex];
            int numDefense = 0;
            for(int j = 0; j < numContaining; ++j){
                currentIndex++;
                numDefense = (numDefense*256) + input[currentIndex] + 128;
            }
            
            DefenseType type = DefenseType.values()[defenseID];
            
            defenses.put(type, numDefense);
            currentIndex++;
        }
        return defenses;
    }
    
    public byte[] encode(){
        ArrayList<Byte> theList = new ArrayList<>();
        
        theList.add(Byte.parseByte("" + this.keySet().size()));
        
        for(DefenseType type: this.keySet()){
            int defenseID = type.ordinal();
            theList.add(Byte.parseByte("" + defenseID));
            
            int count = 0;
            int value = this.get(type);
            if(value != 0){
                count = (int)Math.floor(Math.log(value)/Math.log(256)) + 1;
            }else{
                count = 1;
            }
            theList.add(Byte.parseByte("" + count));
            
            for(int j = count - 1; j >= 0; --j){
                int mod = (int)Math.floor(value/Math.pow(256, j));
                value -= mod*Math.pow(256, j);
                mod -= 128;
                theList.add(Byte.parseByte("" + mod));
            }
        }
        Byte[] resultByte = new Byte[theList.size()];
        resultByte = theList.toArray(resultByte);

        byte[] result = new byte[theList.size()];
        for(int i = 0; i < result.length; ++i){
            result[i] = resultByte[i];
        }
        return result;
    }
    
    public static boolean unitTest(){
        
        Defenses defenses = new Defenses();
        
        int i = 0; 
        for(DefenseType type: DefenseType.values()){
            defenses.put(type, i);
            i++;
        }
        
        int value = 6553118;
        defenses.put(DefenseType.ION_CANNON, value);
        
        i = 0;
        
        Defenses result = Defenses.parseDefenses(defenses.encode());
        for(DefenseType type: DefenseType.values()){
            if(type == DefenseType.ION_CANNON){
                if(result.get(type) != value){
                    System.out.println("With type: " + type + " got: " + result.get(type) + 
                            ". Expected: " + value);
                    return false;
                }
            }else if(result.get(type) != i){
                System.out.println("With type: " + type + " got: " + result.get(type) + 
                        ". Expected: " + i);
                return false;
            }
            i++;
        }
        
        result = Defenses.parseDefenses(new Defenses().encode());
        if(result.keySet().size() != 0){
            System.out.println("Key set should be non-zero.  It is: " + result.keySet().size());
            return false;
        }
        
        return true;
    }
}
